﻿using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesRaster;

namespace MyGIS.Forms
{
    public partial class InterpolationForm : Form
    {
        private AxMapControl _mapControl;

        public InterpolationForm(AxMapControl mapControl)
        {
            InitializeComponent();
            _mapControl = mapControl;
        }

        private void InterpolationForm_Load(object sender, EventArgs e)
        {
            // 绑定图层列表
            IMap map = _mapControl.Map;
            for (int i = 0; i < map.LayerCount; i++)
            {
                ILayer layer = map.get_Layer(i);
                if (layer is IFeatureLayer)
                {
                    cmbPointLayer.Items.Add(layer.Name);
                    cmbClipLayer.Items.Add(layer.Name);
                }
            }

            // 事件绑定
            cmbPointLayer.SelectedIndexChanged += cmbPointLayer_SelectedIndexChanged;
            cmbClipLayer.SelectedIndexChanged += cmbClipLayer_SelectedIndexChanged;
            btnSelectOutput.Click += btnSelectOutput_Click;
            btnStartInterpolation.Click += btnStartInterpolation_Click;
            btnInterpolationCancel.Click += btnInterpolationCancel_Click;
        }

        private async void btnStartInterpolation_Click(object sender, EventArgs e)
        {
            // 禁用按钮防止重复点击
            btnStartInterpolation.Enabled = false;
            btnStartInterpolation.Text = "处理中...";

            try
            {
                // 获取选中的图层
                IFeatureLayer pointLayer = GetLayerByName(cmbPointLayer.SelectedItem?.ToString());
                IFeatureLayer clipLayer = GetLayerByName(cmbClipLayer.SelectedItem?.ToString());

                if (pointLayer == null || clipLayer == null)
                {
                    MessageBox.Show("请选择有效的点图层和裁剪图层！");
                    return;
                }

                // 获取字段名
                string fieldName = cmbFields.SelectedItem?.ToString()?.Trim();
                if (string.IsNullOrEmpty(fieldName))
                {
                    MessageBox.Show("请选择用于插值的数值字段！");
                    return;
                }

                // 获取输出路径
                string outputRaster = txtOutputRaster.Text;
                if (string.IsNullOrEmpty(outputRaster))
                {
                    MessageBox.Show("请指定输出栅格文件路径！");
                    return;
                }

                // 异步执行插值操作
                bool success = await Task.Run(() =>
                {
                    try
                    {
                        // 从图层获取实际shp文件路径
                        string pointPath = GetShapefilePathFromLayer(pointLayer);
                        string clipPath = GetShapefilePathFromLayer(clipLayer);

                        if (string.IsNullOrEmpty(pointPath) || string.IsNullOrEmpty(clipPath))
                        {
                            MessageBox.Show("无法获取图层对应的Shapefile路径！");
                            return false;
                        }

                        string scriptPath = @"E:\vsm\zuoye\interpolate_and_clip.py";

                        // 检查输出目录是否存在
                        string outputDir = Path.GetDirectoryName(outputRaster);
                        if (!Directory.Exists(outputDir))
                        {
                            Directory.CreateDirectory(outputDir);
                        }

                        return RunPythonScript(scriptPath, pointPath, fieldName, outputRaster, clipPath);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"插值过程中出错：\n{ex.Message}");
                        return false;
                    }
                });

                // 处理结果
                if (success)
                {
                    if (File.Exists(outputRaster))
                    {
                        // 在主线程更新UI
                        this.Invoke((MethodInvoker)delegate
                        {
                            // 使用输出文件名作为图层名称的基础
                            string layerName = Path.GetFileNameWithoutExtension(outputRaster);
                            AddRasterToMap(outputRaster, layerName);
                            MessageBox.Show("插值成功！结果已添加到地图。");
                        });
                    }
                }
                else
                {
                    MessageBox.Show("插值失败，请检查错误日志！");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发生未处理的异常：\n{ex.Message}");
            }
            finally
            {
                // 恢复按钮状态
                btnStartInterpolation.Enabled = true;
                btnStartInterpolation.Text = "开始插值";
            }
        }

        private bool RunPythonScript(string scriptPath, string pointShp, string fieldName, string outputTif, string clipShp)
        {
            string pythonPath = GetPythonPath();
            if (string.IsNullOrEmpty(pythonPath))
            {
                MessageBox.Show("未找到有效的Python路径！");
                return false;
            }

            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = pythonPath,
                    Arguments = $"\"{scriptPath}\" \"{pointShp}\" \"{fieldName}\" \"{outputTif}\" \"{clipShp}\"",
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = Path.GetDirectoryName(scriptPath)
                };

                using (Process process = new Process { StartInfo = psi })
                {
                    StringBuilder output = new StringBuilder();
                    StringBuilder error = new StringBuilder();

                    // 异步读取输出流
                    process.OutputDataReceived += (sender, e) => output.AppendLine(e.Data);
                    process.ErrorDataReceived += (sender, e) => error.AppendLine(e.Data);

                    process.Start();
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // 设置超时（5分钟）
                    if (!process.WaitForExit(300000))
                    {
                        process.Kill();
                        MessageBox.Show("Python脚本执行超时（5分钟）");
                        return false;
                    }

                    // 记录日志
                    File.WriteAllText(@"D:\Temp\python_stdout.txt", output.ToString());
                    File.WriteAllText(@"D:\Temp\python_stderr.txt", error.ToString());

                    if (process.ExitCode != 0)
                    {
                        MessageBox.Show($"Python脚本返回错误代码：{process.ExitCode}\n错误信息：\n{error.ToString()}");
                        return false;
                    }

                    return true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"启动Python进程失败：\n{ex.Message}");
                return false;
            }
        }

        private void cmbPointLayer_SelectedIndexChanged(object sender, EventArgs e)
        {
            var layerName = cmbPointLayer.SelectedItem?.ToString();
            if (layerName == null) return;

            var layer = GetLayerByName(layerName);
            if (layer == null) return;

            LoadNumericFieldsToComboBox(layer);

            // 自动填充 txtPointPath
            string shpPath = GetShapefilePathFromLayer(layer);
            if (!string.IsNullOrEmpty(shpPath))
                txtPointPath.Text = shpPath;
        }

        private void cmbClipLayer_SelectedIndexChanged(object sender, EventArgs e)
        {
            var layerName = cmbClipLayer.SelectedItem?.ToString();
            if (layerName == null) return;

            var layer = GetLayerByName(layerName);
            if (layer == null) return;

            string shpPath = GetShapefilePathFromLayer(layer);
            if (!string.IsNullOrEmpty(shpPath))
                txtClipPath.Text = shpPath;
        }

        private string GetShapefilePathFromLayer(IFeatureLayer featureLayer)
        {
            try
            {
                if (featureLayer?.FeatureClass != null)
                {
                    IDataset dataset = featureLayer.FeatureClass as IDataset;
                    string folder = dataset.Workspace.PathName;
                    string fileName = dataset.Name;

                    // 判断是否为 shapefile
                    if (dataset.Workspace.Type == esriWorkspaceType.esriFileSystemWorkspace)
                    {
                        string fullPath = Path.Combine(folder, fileName + ".shp");
                        return File.Exists(fullPath) ? fullPath : "";
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("获取图层路径失败：" + ex.Message);
            }
            return "";
        }

        private void btnSelectOutput_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog
            {
                Title = "选择输出栅格文件保存路径",
                Filter = "GeoTIFF 文件 (*.tif)|*.tif",
                DefaultExt = "tif",
                AddExtension = true,
                OverwritePrompt = true,
                // 自动生成包含字段名和时间戳的默认文件名
                FileName = $"插值结果_{cmbFields.SelectedItem?.ToString() ?? "field"}_{DateTime.Now:yyyyMMddHHmmss}.tif",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            };

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                txtOutputRaster.Text = sfd.FileName;
                string folder = Path.GetDirectoryName(sfd.FileName);
                if (!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }
            }
        }

        private void LoadNumericFieldsToComboBox(IFeatureLayer layer)
        {
            cmbFields.Items.Clear();
            if (layer?.FeatureClass == null) return;

            IFields fields = layer.FeatureClass.Fields;
            for (int i = 0; i < fields.FieldCount; i++)
            {
                IField field = fields.get_Field(i);
                if (field.Type == esriFieldType.esriFieldTypeDouble ||
                    field.Type == esriFieldType.esriFieldTypeInteger)
                {
                    cmbFields.Items.Add(field.Name);
                }
            }
        }

        private IFeatureLayer GetLayerByName(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;

            for (int i = 0; i < _mapControl.Map.LayerCount; i++)
            {
                ILayer layer = _mapControl.Map.get_Layer(i);
                if (layer is IFeatureLayer fl && layer.Name == name)
                    return fl;
            }
            return null;
        }

        private void AddRasterToMap(string rasterPath, string baseLayerName)
        {
            try
            {
                IRaster raster = LoadRasterFromFile(rasterPath);
                IRasterLayer rasterLayer = new RasterLayerClass();
                rasterLayer.CreateFromRaster(raster);

                // 生成唯一图层名称
                string uniqueLayerName = GetUniqueLayerName(baseLayerName);
                rasterLayer.Name = uniqueLayerName;

                IMap map = _mapControl.Map;
                map.AddLayer(rasterLayer);
                _mapControl.Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show("添加栅格图层失败：" + ex.Message);
            }
        }
        private string GetUniqueLayerName(string baseName)
        {
            IMap map = _mapControl.Map;
            string layerName = baseName;
            int counter = 1;

            // 检查是否已存在同名图层
            while (LayerExists(map, layerName))
            {
                layerName = $"{baseName}_{counter}";
                counter++;
            }

            return layerName;
        }

        private bool LayerExists(IMap map, string layerName)
        {
            for (int i = 0; i < map.LayerCount; i++)
            {
                if (map.get_Layer(i).Name == layerName)
                    return true;
            }
            return false;
        }


        private IRaster LoadRasterFromFile(string rasterPath)
        {
            try
            {
                IRasterWorkspace rasterWorkspace = new RasterWorkspaceFactoryClass()
                    .OpenFromFile(Path.GetDirectoryName(rasterPath), 0) as IRasterWorkspace;

                IRasterDataset rasterDataset = rasterWorkspace.OpenRasterDataset(Path.GetFileName(rasterPath));
                return rasterDataset.CreateDefaultRaster();
            }
            catch (Exception ex)
            {
                MessageBox.Show("加载栅格文件失败：" + ex.Message);
                return null;
            }
        }

        private string GetPythonPath()
        {
            // 可改为配置或环境变量获取
            return @"D:\anaconda\anacanda\python.exe";
        }

        private void btnInterpolationCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cmbPointLayer_SelectedIndexChanged_1(object sender, EventArgs e)
        {

        }
    }
}